﻿namespace PowerSong.Import
    {
    using Modern = PowerSong.SongDatabase;
    using Legacy = PowerSong.SongDatabase.Legacy;
    using PowerSong.SongDatabase.Legacy.Items;
    using System;

    public static class LegacyConverter
        {

        private const int FramesToMillisecondsMultiplier = 50;

        private const double FontSizeDivisor = 100D;

        public static Modern.Song ConvertSong(SongItem legacySong)
            {

            // Compose the modern song
            var newSong = new Modern.Song(legacySong.Title, legacySong.Parts.ToArray());
            newSong.ID = legacySong.SongID;
            newSong.Authors.AddRange(legacySong.Authors);
            newSong.Copyright = legacySong.CopyrightLine;

            // Return the modern song
            return newSong;

            }

        public static Modern.Style ConvertStyle(Legacy.Style style)
            {

            // Compose the modern style
            var newStyle = new SongDatabase.Style(style.Name)
                {
                ID = style.StyleID,
                BackgroundColor = (uint)style.DefaultBackgroundColour.ToArgb(),
                BackgroundFileName = style.DefaultBackgroundImage
                };

            // Add substyles (which used to be called projectlets)
            foreach (Legacy.ProjectletStyle subStyle in style.Projectlets)
                {

                // Validate the component name
                if (subStyle.Category != "Title" && subStyle.Category != "Verse" && subStyle.Category != "Copyright")
                    {
                    throw new Exception("The style '" + style.Name + "' contains an unrecognised type of element.");
                    }

                // Create the new substyle
                var newSubStyle = new Modern.SubStyle(subStyle.Category)
                    {
                    Margin = new Modern.SubStyleMargin(subStyle.Area.Left,
                                                       subStyle.Area.Top,
                                                       1 - subStyle.Area.Right,
                                                       1 - subStyle.Area.Bottom),
                    FadeIn = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.GeneralFadeDuration * FramesToMillisecondsMultiplier),
                    FadeOut = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.GeneralFadeDuration * FramesToMillisecondsMultiplier),
                    CrossFade = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.VerseFadeDuration * FramesToMillisecondsMultiplier),
                    FontName = subStyle.FontName,
                    TextAlignment = ConvertTextAlignment(style.Name, subStyle.Alignment),
                    FontSize = subStyle.FontSize / FontSizeDivisor,
                    FontStyle = ConvertFontStyle(subStyle.FontStyle),
                    FontColor = (uint)subStyle.FontColour.ToArgb(),
                    FontEffect = ConvertFontEffect(style.Name, subStyle.FontEffect),
                    FontEffectColor = (uint)subStyle.FontEffectColour.ToArgb(),
                    Visibility = ConvertVisibility(style.Name, subStyle.DisplayOption)
                    };
                newStyle.AddSubStyle(newSubStyle);

                }

            // Return the modern style
            return newStyle;

            }

        public static Modern.Style ConvertStyle(Legacy.Data dataSet, Legacy.Data.StylesRow style)
            {

            // Compose the modern style
            var newStyle = new SongDatabase.Style(style.Name)
                {
                ID = style.StyleID,
                BackgroundColor = (uint)style.DefaultBackgroundColour,
                BackgroundFileName = style.DefaultBackgroundImage
                };

            // Add substyles (which used to be called projectlets)
            foreach (Legacy.Data.ProjectletsRow subStyle in dataSet.Projectlets.Select("StyleID='" + style.StyleID.ToString() + "'"))
                {

                // Validate the component name
                if (subStyle.Component != "Title" && subStyle.Component != "Verse" && subStyle.Component != "Copyright")
                    {
                    throw new Exception("The style '" + style.Name + "' contains an unrecognised type of element.");
                    }

                // Create the new substyle
                var newSubStyle = new Modern.SubStyle(subStyle.Component)
                    {
                    Margin = new Modern.SubStyleMargin(subStyle.AreaLeft,
                                                       subStyle.AreaTop,
                                                       1 - (subStyle.AreaLeft + subStyle.AreaWidth),
                                                       1 - (subStyle.AreaTop + subStyle.AreaHeight)),
                    FadeIn = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.GeneralFadeDuration * FramesToMillisecondsMultiplier),
                    FadeOut = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.GeneralFadeDuration * FramesToMillisecondsMultiplier),
                    CrossFade = new Modern.SubStyleFadeDetails(Modern.FadeType.Fade, style.VerseFadeDuration * FramesToMillisecondsMultiplier),
                    FontName = subStyle.FontName,
                    TextAlignment = ConvertTextAlignment(style.Name, (Legacy.Style.ETextAlignment)subStyle.Alignment),
                    FontSize = subStyle.FontSize / FontSizeDivisor,
                    FontStyle = ConvertFontStyle((System.Drawing.FontStyle)subStyle.FontStyle),
                    FontColor = (uint)subStyle.FontColour,
                    FontEffect = ConvertFontEffect(style.Name, (Legacy.Style.ETextEffect)subStyle.FontEffect),
                    FontEffectColor = (uint)subStyle.FontEffectColour,
                    Visibility = ConvertVisibility(style.Name, (Legacy.Style.EDisplayOption)subStyle.WhenToDisplay)
                    };
                newStyle.AddSubStyle(newSubStyle);

                }

            // Return the modern style
            return newStyle;

            }

        private static Modern.Alignment ConvertTextAlignment(string styleName, Legacy.Style.ETextAlignment alignment)
            {
            switch (alignment)
                {
                case Legacy.Style.ETextAlignment.TopLeft: return Modern.Alignment.LeftTop;
                case Legacy.Style.ETextAlignment.TopMiddle: return Modern.Alignment.CenterTop;
                case Legacy.Style.ETextAlignment.TopRight: return Modern.Alignment.RightTop;
                case Legacy.Style.ETextAlignment.MiddleLeft: return Modern.Alignment.LeftMiddle;
                case Legacy.Style.ETextAlignment.MiddleMiddle: return Modern.Alignment.CenterMiddle;
                case Legacy.Style.ETextAlignment.MiddleRight: return Modern.Alignment.RightMiddle;
                case Legacy.Style.ETextAlignment.BottomLeft: return Modern.Alignment.LeftBottom;
                case Legacy.Style.ETextAlignment.BottomMiddle: return Modern.Alignment.CenterBottom;
                case Legacy.Style.ETextAlignment.BottomRight: return Modern.Alignment.RightBottom;
                default: throw new Exception("Alignment details for style '" + styleName + "' cannot be converted.");
                }
            }

        public static Modern.FontEffectType ConvertFontStyle(System.Drawing.FontStyle style)
            {
            var result = Modern.FontEffectType.None;
            if ((style & System.Drawing.FontStyle.Bold) == System.Drawing.FontStyle.Bold) result |= Modern.FontEffectType.Bold;
            if ((style & System.Drawing.FontStyle.Italic) == System.Drawing.FontStyle.Italic) result |= Modern.FontEffectType.Italic;
            if ((style & System.Drawing.FontStyle.Underline) == System.Drawing.FontStyle.Underline) result |= Modern.FontEffectType.Underline;
            if ((style & System.Drawing.FontStyle.Strikeout) == System.Drawing.FontStyle.Strikeout) result |= Modern.FontEffectType.Underline;
            return result;
            }

        private static Modern.TextEffectType ConvertFontEffect(string styleName, Legacy.Style.ETextEffect effect)
            {
            switch (effect)
                {
                case Legacy.Style.ETextEffect.FilledBox: return Modern.TextEffectType.FillRectangle;
                case Legacy.Style.ETextEffect.InnerOutline: return Modern.TextEffectType.OutlineText;
                case Legacy.Style.ETextEffect.None: return Modern.TextEffectType.None;
                case Legacy.Style.ETextEffect.Outline: return Modern.TextEffectType.OutlineText;
                case Legacy.Style.ETextEffect.OutlineBox: return Modern.TextEffectType.DrawRectangle;
                case Legacy.Style.ETextEffect.Shadow: return Modern.TextEffectType.ShadowText;
                default: throw new Exception("Font effect details for style '" + styleName + "' cannot be converted.");
                }
            }

        private static Modern.TextVisibility ConvertVisibility(string styleName, Legacy.Style.EDisplayOption option)
            {

            // For some reason, -1 is a possibility (ie: in old style export files on the website), so translate it to "Always"
            if ((int)option == -1) return Modern.TextVisibility.Always;

            // Translate normal options
            switch (option)
                {
                case Legacy.Style.EDisplayOption.Always: return Modern.TextVisibility.Always;
                case Legacy.Style.EDisplayOption.FirstVerse: return Modern.TextVisibility.FirstVerseAlways;
                case Legacy.Style.EDisplayOption.FirstVerseOnce: return Modern.TextVisibility.FirstVerseOnce;
                case Legacy.Style.EDisplayOption.LastVerse: return Modern.TextVisibility.LastVerseAlways;
                case Legacy.Style.EDisplayOption.LastVerseOnce: return Modern.TextVisibility.LastVerseOnce;
                case Legacy.Style.EDisplayOption.Never: return Modern.TextVisibility.Never;
                case Legacy.Style.EDisplayOption.SecondVerse: return Modern.TextVisibility.LastVerseAlways;
                case Legacy.Style.EDisplayOption.SecondVerseOnce: return Modern.TextVisibility.LastVerseOnce;
                default: throw new Exception("Visibility details for style '" + styleName + "' cannot be converted.");
                }

            }

        public static SongDatabase.License ConvertLicense(SongDatabase.Legacy.License oldLicense)
            {
            var newLicense = new SongDatabase.License();
            newLicense.ID = oldLicense.LicenseID;
            newLicense.Name = oldLicense.Name;
            newLicense.Number = oldLicense.Number;
            newLicense.Description = oldLicense.Details;
            return newLicense;
            }

        }

    }
